package org.dalmatian.common.translation.core;

import org.dalmatian.common.core.utils.StringUtils;
import org.dalmatian.common.translation.annotation.Translation;
import org.dalmatian.common.translation.context.TranslationContext;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Component;

@Component
@Slf4j
@RequiredArgsConstructor
public class TranslationServiceImpl implements TranslationService {

    private final TranslationCache translationCache;

    @Override
    public void process(TranslationContext context) {
        try {
            Object sourceValue = context.getSourceValue();
            if (sourceValue == null && !context.getAnnotation().nullable()) {
                return;
            }

            Translation annotation = context.getAnnotation();
            String result = translationCache.get(annotation.type(), context.getTargetObject(),
                annotation.other());
            if (StringUtils.isEmpty(result)) {
                return;
            }
            context.setTranslatedValue(result);
        } catch (Exception e) {
            log.error("Translation process failed", e);
        }
    }

    @Override
    public void batchProcess(List<TranslationContext> contexts) {
        if (contexts.isEmpty()) {
            return;
        }

        contexts.stream()
            .collect(Collectors.groupingBy(TranslationContext::getAnnotation))
            .forEach((annotation, ctxList) -> {
                Set<String> keys = ctxList.stream()
                    .map(TranslationContext::getSourceValue)
                    .filter(Objects::nonNull)
                    .flatMap(sourceValue ->
                        sourceValue instanceof List ? ((List<?>) sourceValue).stream() : Stream.of(sourceValue))
                    .map(String::valueOf)
                    .collect(Collectors.toSet());

                if (keys.isEmpty()) {
                    return;
                }
                Map<String, String> translations = translationCache
                    .batchFindByTypeAndCodes(annotation.type(), keys, annotation.other());

                ctxList.forEach(ctx -> {
                    Object translatedValue = TranslationContext.isListOfString(ctx.getTargetField())
                        ? ((List<?>) ctx.getSourceValue()).stream()
                        .map(o -> translations.get(String.valueOf(o)))
                        .collect(Collectors.toList())
                        : translations.get(String.valueOf(ctx.getSourceValue()));
                    if (translatedValue != null) {
                        try {
                            ctx.setTranslatedValue(translatedValue);
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
            });
    }
}